from socket import error as socket_error
import socket
import threading
import abc
import time

class AbstractNodeKomunikacija:
    __metaclass__ = abc.ABCMeta
    
    def __init__(self, listenPort):
        self.running = True
        self.stopping = False
        self.listenPort = listenPort
        self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.recieveSocket = None
        
    def sendPaketWithCustomHeader(self, fromAddress, fromPort, sendAddress, sendPort, requestID, komanda, teloPoruke):
        print "AbstractNodeKomunikacija: Saljem poruku:\n"
        print str(sendAddress) + " " + str(sendPort) + " " + str(requestID) + " " + str(komanda) + " " + str(teloPoruke)
        sendSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        #NAPRAVI HEADER
        #adresa|port|requesID|komanda|telo
        request = str(socket.gethostbyaddr(fromAddress)[0]) + "|" + str(fromPort) + "|" + str(requestID) + "|" + str(komanda) + "|" + str(teloPoruke)
        sendSocket.sendto(request, (sendAddress, int(sendPort)))
        sendSocket.close();
    
    def sendPaket(self, sendAddress, sendPort, requestID, komanda, teloPoruke):
        self.sendPaketWithCustomHeader(socket.gethostname(), self.listenPort, sendAddress, sendPort, requestID, komanda, teloPoruke)
    
    @abc.abstractmethod
    def obradiPaket(self, recieveAddress, recievePort, requestID, komanda, telo):
        print "NE TREBA OVO DA SE ZOVE U ABSTRACTKOMUNIKACIJI"
        return
        
    def recieveMethod(self):
        self.running=True
        self.recieveSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        #print socket.gethostname(), " ", int(self.listenPort)
        self.recieveSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR   , 1) #da moze da rijuzjue adres  proveriti ms
        self.recieveSocket.bind((socket.gethostname(), int(self.listenPort)))
        #print "BIND"
        self.recieveSocket.setblocking(0)
        print "AbstractNodeKomunikacija: pocinjem da slusam"
        while self.running:
            time.sleep(0.001)
            # citanje poruke
            data =""
            try:
                data, addr = self.recieveSocket.recvfrom(10000)
                #print data
            except socket_error as serr:
                if(not self.running):
                    print "OVO JE OK EXECPTION"
                    #raise serr
            #print "kk"
            if(data.__len__()<1):
                continue
            data = data.split('|') #prokleti pajp je italik sve je italik
            recieveAddress = data[0]
            recievePort = data[1]
            requestID = data[2]
            komanda = data[3]
            telo = data[4]
            print "AbstractNodeKomunikacija: Primio sam poruku:\n"
            print recieveAddress + " " + recievePort + " " + requestID + " " + komanda + " " + telo
            self.obradiPaket(recieveAddress, recievePort, requestID, komanda, telo)
        print "AbstractNodeKomunikacija: prestajem da slusam"
        self.recieveSocket.close()
    
    def startRecieving(self):
        self.running = True
        self.stopping = False
        t = threading.Thread(target=self.recieveMethod, args=())
        t.daemon = True
        t.start()
        
    def stopRecieving(self):
        self.stopping = True;
        self.running = False;
        while self.recieveSocket is None:
            #print "g"
            continue
        self.recieveSocket.close()
        
        
        
